package com.cysyz.mylib.commonservice.statisticsupport.impl;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import com.cysyz.mylib.commonservice.statisticsupport.DailyJobsService;
import com.cysyz.mylib.commonservice.statisticsupport.StatisticTimeAble;
import com.cysyz.mylib.commonservice.statisticsupport.StatisticTimeService;
import com.cysyz.mylib.commonservice.statisticsupport.vo.StatisticableVO;
import com.cysyz.mylib.dao.PagingResult;
import com.cysyz.mylib.utils.DateUtil;
import com.cysyz.mylib.utils.DateUtil.BeginOrEnd;
import com.cysyz.mylib.utils.MyReflectionUtils;

public abstract class AbstractDailyStatisticServiceImpl<E extends StatisticTimeAble> extends AbstractStatisticServiceImpl implements DailyJobsService{
	@SuppressWarnings("unchecked")
	private Class<E> StatisticTimeAbleClazz = MyReflectionUtils.getActualType(this.getClass(), 0);
	
	private static String statisticName;
	
	@Resource
	private StatisticTimeService statisticTimeService;
	
	@PostConstruct
	public void postConstruct() {
		statisticName = this.getClass().getName();
	}
	
	@Override
	public <T> PagingResult<T> searchAllStatisticList(Class<T> clazz,
			StatisticableVO searchvo, int page, int pageSize) {
		
		if ("today".equals(searchvo.getDateType())) {
			Integer lastRunDailyJobTimeSeconds = statisticTimeService.searchLastRunDailyJobTimeSeconds(statisticName);
			//如果当前的日期与最后一次进行了统计的日期不在同一天,那么就设置最后一次统计的时间为null,并且设置定时统计前一天的数据的开始时间
			if (lastRunDailyJobTimeSeconds != null) {
				String lastRunDailyJobDate = DateUtil.getTimeString(lastRunDailyJobTimeSeconds);
				String currentDate = DateUtil.getCurrentDate();
				if (!lastRunDailyJobDate.equals(currentDate)) {
					statisticTimeService.saveLastDateAlreadyStatisticedSeconds(StatisticTimeAbleClazz, statisticName, lastRunDailyJobTimeSeconds);
					statisticTimeService.saveLastRunDailyJobTimeSeconds(StatisticTimeAbleClazz, statisticName, null);
					lastRunDailyJobTimeSeconds = null;
				}
			}
			
			if (lastRunDailyJobTimeSeconds == null
					|| DateUtil.getLast2hourIntTime() >= lastRunDailyJobTimeSeconds) {
				//统计今天的数据
				int startDateTimeSeconds = lastRunDailyJobTimeSeconds == null ? DateUtil.getIntDateTime(DateUtil.getCurrentDate()) : lastRunDailyJobTimeSeconds;
				int endDateTimeSeconds = DateUtil.getDateTime();
				statisticTimeService.saveLastRunDailyJobTimeSeconds(StatisticTimeAbleClazz, statisticName, endDateTimeSeconds);
				saveExecute(startDateTimeSeconds, endDateTimeSeconds);
			}
		}
		return super.searchAllStatisticList(clazz, searchvo, page, pageSize);
	}
	
	//每日凌晨3点统计前一天的数据
	public void saveExecute() {
		//取得前一天
		String lastDate = DateUtil.getStringDateTime(-1);
		int startDateTimeSeconds = DateUtil.getIntDateTime(lastDate);
		Integer lastRunDailyJobTimeSeconds = statisticTimeService.searchLastRunDailyJobTimeSeconds(statisticName);
		String lastRunDailyJobDate = DateUtil.getTimeString(lastRunDailyJobTimeSeconds);
		String currentDate = DateUtil.getCurrentDate();
		//如果lastRunDailyJobDate中的日期不是今天，说明在定时统计之前没有人查询当天的数据，那么就定时统计最后一次被查询的时间到前一天结束时间之间的信息。
		if (!lastRunDailyJobDate.equals(currentDate)) {
			startDateTimeSeconds = lastRunDailyJobTimeSeconds;
			statisticTimeService.saveLastRunDailyJobTimeSeconds(StatisticTimeAbleClazz, statisticName, DateUtil.getIntDateTime(currentDate));
		}

		//如果在定时统计之前有人查询了当天的统计数据，那么系统会首先会把前一天最后查询的时间保存到lastDateAlreadyStatisticedSeconds中，以备定时统计使用。之后再统计当天开始到查询时的时间的信息。
		Integer lastDateAlreadyStatisticedSeconds = statisticTimeService.searchLastDateAlreadyStatisticedSeconds(statisticName);
		//如果前一天已经有了部分的统计，那么就统计剩余未被统计上的信息。
		if (lastDateAlreadyStatisticedSeconds  != null) {
			startDateTimeSeconds = lastDateAlreadyStatisticedSeconds;
			statisticTimeService.saveLastDateAlreadyStatisticedSeconds(StatisticTimeAbleClazz, statisticName, null);
		}
		
		int endDateTimeSeconds = DateUtil.getIntDateTime(lastDate, BeginOrEnd.end);
		saveExecute(startDateTimeSeconds, endDateTimeSeconds);
	}

	protected void saveExecute(int startDateTimeSeconds, int endDateTimeSeconds ) {
		
		String currentDate = DateUtil.getTimeString(startDateTimeSeconds);
		
		StringBuilder sql = new StringBuilder();
		
		List<Object> params = new ArrayList<Object>();
		saveExecuteInternal(currentDate, sql, params);
		
		params.add(startDateTimeSeconds);
		params.add(endDateTimeSeconds);
		this.executeSql(sql.toString(), params );
	}

	protected abstract void saveExecuteInternal(String currentDate, StringBuilder sql, List<Object> params);
}
